package org.convallaria.infrastruct.db.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.plugin.Interceptor;
import org.convallaria.infrastruct.db.handler.DefaultDBFieldHandler;
import org.convallaria.infrastruct.db.interceptor.SlowSqlInterceptor;
import org.convallaria.infrastruct.db.interceptor.QueryCacheInterceptor;
import org.convallaria.infrastruct.db.monitor.DataSourceMonitor;
import org.convallaria.infrastruct.db.properties.CustomDataSourceProperties;
import org.convallaria.infrastruct.db.util.QueryCacheManager;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

/**
 * MyBatis-Plus 自动配置类
 * 
 * 提供企业级MyBatis-Plus增强功能，包括：
 * - 分页插件配置（支持MySQL）
 * - 乐观锁插件（防止并发更新冲突）
 * - 防全表更新删除插件（数据安全保护）
 * - 高性能慢SQL监控（可配置阈值和日志级别）
 * - 数据源连接池监控（JMX支持）
 * - 自动字段填充（创建时间、更新时间、操作人等）
 * - 查询缓存管理（提升查询性能）
 * 
 * 配置特性：
 * - 条件化Bean创建，避免不必要的组件加载
 * - 详细的配置日志，便于问题排查
 * - 支持多环境配置覆盖
 * - 与Spring Boot自动配置完美集成
 * 
 * @author gjh
 * @since 2024-09-22
 */
@Slf4j
@AutoConfiguration(after = MybatisPlusAutoConfiguration.class)
@EnableConfigurationProperties(CustomDataSourceProperties.class)
@MapperScan("org.convallaria.**.mapper")
public class CustomMyBatisPlusAutoConfig {

    public CustomMyBatisPlusAutoConfig() {
        log.info("=== MyBatis-Plus 自动配置启动 ===");
    }

    /**
     * MyBatis-Plus 拦截器配置
     */
    @Bean
    @ConditionalOnMissingBean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        // 分页插件
        PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();
        paginationInterceptor.setDbType(DbType.MYSQL);
        paginationInterceptor.setOverflow(false);
        paginationInterceptor.setMaxLimit(1000L);
        interceptor.addInnerInterceptor(paginationInterceptor);
        
        // 乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        
        // 防止全表更新与删除插件
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        
        log.info("MyBatis-Plus 拦截器配置完成");
        return interceptor;
    }

    /**
     * 自动填充配置
     *
     * @return MetaObjectHandler
     */
    @Bean
    @ConditionalOnMissingBean
    public MetaObjectHandler metaObjectHandler() {
        return new DefaultDBFieldHandler();
    }

    /**
     * 高性能慢SQL拦截器配置
     * 根据配置决定是否启用慢SQL监控
     *
     * @param properties 数据源配置属性
     * @return OptimizedSlowSqlInterceptor
     */
    @Bean
    @ConditionalOnProperty(prefix = "convallaria.datasource.slow-sql", name = "enabled", havingValue = "true", matchIfMissing = true)
    public Interceptor optimizedSlowSqlInterceptor(CustomDataSourceProperties properties) {
        SlowSqlInterceptor interceptor = new SlowSqlInterceptor();
        
        // 构建拦截器配置属性
        java.util.Properties props = buildInterceptorProperties(properties);
        interceptor.setProperties(props);
        
        log.info("高性能慢SQL拦截器配置完成 - 阈值: {}ms, SQL日志: {}, 参数记录: {}, 日志级别: {}", 
            properties.getSlowSql().getThreshold(), 
            properties.getSlowSql().getEnableLog(),
            properties.getSlowSql().getLogParameters(),
            properties.getSlowSql().getLogLevel());
            
        return interceptor;
    }

    /**
     * 构建拦截器配置属性
     */
    private java.util.Properties buildInterceptorProperties(CustomDataSourceProperties properties) {
        java.util.Properties props = new java.util.Properties();
        
        CustomDataSourceProperties.SlowSql slowSql = properties.getSlowSql();
        props.setProperty("slowSqlThreshold", String.valueOf(slowSql.getThreshold()));
        props.setProperty("enableSqlLog", String.valueOf(slowSql.getEnableLog()));
        props.setProperty("logParameters", String.valueOf(slowSql.getLogParameters()));
        props.setProperty("logLevel", slowSql.getLogLevel());
        props.setProperty("maxSqlLength", String.valueOf(slowSql.getMaxSqlLength()));
        // 默认启用统计
        props.setProperty("enableStatistics", "true");
        
        return props;
    }

    /**
     * 数据源性能监控配置
     * 提供数据源连接池监控功能
     */
    @Bean
    @ConditionalOnProperty(prefix = "convallaria.datasource.monitor", name = "enabled", havingValue = "true", matchIfMissing = true)
    public DataSourceMonitor dataSourceMonitor(CustomDataSourceProperties properties) {
        DataSourceMonitor monitor = new DataSourceMonitor(properties.getMonitor());
        log.info("数据源监控器配置完成 - 监控周期: {}秒, JMX: {}", 
            properties.getMonitor().getPeriod(),
            properties.getMonitor().getJmxEnabled());
        return monitor;
    }

    /**
     * 查询缓存管理器配置
     * 提供查询结果缓存功能
     */
    @Bean
    @ConditionalOnProperty(prefix = "convallaria.datasource.performance", name = "cache-enabled", havingValue = "true")
    @ConditionalOnMissingBean
    public QueryCacheManager queryCacheManager(CustomDataSourceProperties properties) {
        CustomDataSourceProperties.Performance performance = properties.getPerformance();
        
        QueryCacheManager cacheManager = new QueryCacheManager(
            performance.getCacheEnabled(),
            performance.getMaxCacheSize(),
            performance.getCacheExpireMinutes().longValue(),
            performance.getCacheCleanupInterval().longValue(),
            performance.getCacheMemoryThreshold()
        );
        
        log.info("查询缓存管理器配置完成 - 启用状态: {}, 最大缓存: {}, 过期时间: {}分钟, 清理间隔: {}分钟, 内存阈值: {}%", 
            performance.getCacheEnabled(),
            performance.getMaxCacheSize(),
            performance.getCacheExpireMinutes(),
            performance.getCacheCleanupInterval(),
            performance.getCacheMemoryThreshold());
            
        return cacheManager;
    }

    /**
     * 查询缓存拦截器配置
     * 自动缓存SELECT查询结果
     */
    @Bean
    @ConditionalOnProperty(prefix = "convallaria.datasource.performance", name = "cache-enabled", havingValue = "true")
    public Interceptor queryCacheInterceptor(QueryCacheManager queryCacheManager) {
        QueryCacheInterceptor interceptor = new QueryCacheInterceptor();
        interceptor.setCacheManager(queryCacheManager);
        
        // 设置拦截器配置
        java.util.Properties props = new java.util.Properties();
        props.setProperty("enableCache", "true");
        props.setProperty("enableSelectCache", "true");
        props.setProperty("enableClearOnUpdate", "true");
        props.setProperty("cacheKeyPrefix", "sql_cache:");
        interceptor.setProperties(props);
        
        log.info("查询缓存拦截器配置完成");
        return interceptor;
    }
}
